package cate.game.train.inscription;

import cate.common.table.d.GDInscription;
import cate.common.table.d.GDOperation;
import cate.common.table.item.inscription.row.InscriptionBaseRow;
import cate.common.util.GameResult;
import cate.game.client.msg.MergeMsgSender;
import cate.game.event.RoleEventPublisher;
import cate.game.event.hero.HeroPowerChangeEvent;
import cate.game.res.MixRes;
import cate.game.res.MixResItem;
import cate.game.role.Role;
import cate.game.role.bag.hero.Hero;
import cate.game.role.bag.inscription.Inscription;
import cate.game.role.bag.inscription.InscriptionPage;
import cate.game.train.inscription.msg.*;
import easy.java.practice.errorcode.EcResult;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

public class TrainInscriptionHandler implements RoleEventPublisher {

    public Hero getHero(Role role, String heroUid) {
        return role.getBag().hero.getItem(heroUid);
    }

    public Inscription getInscription(Role role, String inscriptionUid) {
        return getInscription(role, inscriptionUid, 0, (byte) 0);
    }

    /**
     * 获取铭文对象，有英雄id从英雄身上取，没有则从背包里取
     */
    public Inscription getInscription(Role role, String inscriptionUid, int pageId, byte pos) {
        if (pageId > 0) {
            InscriptionPage page = role.getRes().inscription.pageMap.get(pageId);
            if (page != null) {
                Inscription inscription = role.getBag().inscription.getItem(page.uidMap.get(pos));
                if (StringUtils.equals(inscriptionUid, inscription.uid)) {
                    return inscription;
                }
            }
        } else {
            return role.getBag().inscription.getItem(inscriptionUid);
        }
        return null;
    }

    //将铭文装配上铭文页
    public GameResult<Byte> inscriptionOn(Role role, String inscriptionUid, int pageId, byte pos) {
        GameResult<Byte> r = new GameResult<>();
        Inscription inscription = getInscription(role, inscriptionUid);
        if (inscription == null || inscription.num == 0) {
            return r.fail("铭文不存在");
        }
        InscriptionPage page = role.getRes().inscription.pageMap.get(pageId);
        if (page == null) {
            return r.fail("铭文页不存在");
        }
        r = page.put(pos, inscription);
        if (!r.ok()) {
            return r;
        }
        role.sendNow(new InscriptionOnResp(inscription, page, pos));
        role.getRes().inscription.noticeUpdate();
        role.getHistory().action.inscriptionOn();
        return r;
    }

    public void inscriptionOff(Role role, int pageId, List<Byte> posList) {
        InscriptionPage page = role.getRes().inscription.pageMap.get(pageId);
        if (page == null) {
            role.getGame().notice.message(role, "铭文页不存在");
            return;
        }
        InscriptionOffResp resp = new InscriptionOffResp();
        resp.id = pageId;
        resp.posList = new ArrayList<>();
        EcResult<Byte> r;
        for (byte pos : posList) {
            r = page.off(pos);
            if (r.ok()) {
                resp.posList.add(r.data);
            } else {
                role.getGame().notice.message(role, r.message);
            }
        }
        role.sendNow(resp);
        role.getRes().inscription.noticeUpdate();
    }

    public void pageOn(Role role, int pageId, List<String> heroUids) {
        if (heroUids == null) {
            role.getGame().notice.message(role, "英雄id不能为空");
            return;
        }
        for (String heroUid : heroUids) {
            Hero hero = getHero(role, heroUid);
            if (hero == null) {
                role.getGame().notice.message(role, "有英雄不存在");
                return;
            }
            if (hero.getTpl(role.getGame()).star < GDInscription.HERO_ON_STAR) {
                role.getGame().notice.message(role, "有英雄星级不够");
                return;
            }
        }
        InscriptionPage page = role.getRes().inscription.pageMap.get(pageId);
        if (page == null) {
            role.getGame().notice.message(role, "铭文页不存在");
            return;
        }
        List<String> resultIds = new ArrayList<>(heroUids);
        for (String heroUid : heroUids) {
            GameResult<Hero> r = pageOn(role, pageId, heroUid);
            if (!r.ok()) {
                role.getGame().notice.message(role, r);
                resultIds.remove(r.data.uid);
            }
        }
        role.sendNow(new InscriptionPageOnResp(resultIds, pageId));
        role.getRes().inscription.noticeUpdate();
        role.getHistory().action.inscriptionPageOn();
    }

    public GameResult<Hero> pageOn(Role role, int pageId, String heroUid) {
        Hero hero = getHero(role, heroUid);
        InscriptionPage page = role.getRes().inscription.pageMap.get(pageId);
        return hero.onInscriptionPage(page);
    }

    public void levelUp(Role role,  String insriptionUid) {
        Inscription inscription = getInscription(role, insriptionUid);
        if (inscription == null) {
            role.getGame().notice.message(role, "铭文不存在");
            return;
        }

        InscriptionBaseRow baseRow = inscription.getTpl(role.getGame());
        if (baseRow == null) {
            role.getGame().notice.message(role, "找不到配置");
            return;
        }
        if (baseRow.nextId == 0) {
            role.getGame().notice.message(role, "铭文已升到最高级");
            return;
        }
        //消耗道具
        MixRes consume = new MixRes(baseRow.levelUpCost);
        GameResult<MixResItem> r = consume.consume(role, null);
        if (!r.ok()) {
            role.getGame().notice.message(role, r.message);
            return;
        }
        inscription.levelUp(role.getGame());
        role.sendNow(new InscriptionLevelUpResp(inscription));
        role.getGame().notice.message(role, "升级成功");
        // 如果升级了英雄身上的铭文 则更新战力
        for (InscriptionPage page : role.getRes().inscription.pageMap.values()) {
            if (page != null) {
                if (page.owners.size() > 0 && page.uidMap.containsValue(inscription.uid)) {
                    role.getBase().updatePower();
                    for (String heroUid :
                            page.owners) {
                        if (getHero(role, heroUid) == null) {
                            continue;
                        }
                        publishEvent(role.getGame(), new HeroPowerChangeEvent(role, getHero(role, heroUid)));
                    }
                }
            }
        }
        if (role.getRes().inscription.contains(inscription)) {
            role.getRes().inscription.noticeUpdate();
        }
        role.getHistory().action.inscriptionUpgrade();
    }

    //分解铭文
    public void breakInscription(Role role, Set<String> uids) {
        if (uids.size() > GDInscription.BREAK_NUM) {
            role.getGame().notice.message(role, "分解数量超过上限");
            return;
        }
        List<Inscription> inscriptions = uids.stream().map(uid -> getInscription(role, uid)).filter(Objects::nonNull).collect(Collectors.toList());
        if (inscriptions.size() < uids.size()) {
            role.getGame().notice.message(role, "有不存在的铭文");
            return;
        }
        List<Inscription> bagIns = inscriptions.stream().filter(i -> !role.getRes().inscription.contains(i)).collect(Collectors.toList());
        if (bagIns.size() < inscriptions.size()) {
            role.getGame().notice.message(role, "已镶嵌的铭文不能分解");
            return;
        }
        Optional<MixRes> res = bagIns.stream().map(inscription -> new MixRes(inscription.getTpl(role.toPlayBuildContext()).backReward)).reduce(MixRes::addList);
        if (!res.isPresent() || res.get().isEmpty()) {
            role.getGame().notice.message(role, "奖励不存在");
            return;
        }
        MergeMsgSender sender = new MergeMsgSender();
        for (String uid : uids) {
            role.getBag().inscription.removeItem(uid, sender);
        }
        sender.send(role, true);
        res.get().add(role, true, GDOperation.INSCRIPTION_BREAK);
        role.getGame().notice.dialogReward(role, res.get());
    }

    //解锁铭文格子
    public void openGrid(Role role, int pageId, byte pos) {
        GameResult<InscriptionPage> result = role.getRes().inscription.openGrid(pageId, pos);
        if (!result.ok()) {
            role.getGame().notice.message(role, result);
        } else {
            role.sendNow(new PageOpenGridResp(result.data));
        }
    }
}
